// ----------------------------------------------------------------------------
// serialize_compound_type.h
// ----------------------------------------------------------------------------
// TODO : アロケータの差し替え.
#pragma once
#include <fw/base/runtime/hash.h>
#include <fw/base/serialize/serialize_dictionary.h>
#include <fw/base/serialize/serialize_member.h>
#include <fw/base/serialize/serialize_status.h>
#include <fw/base/serialize/serialize_type.h>

namespace fw
{
	class SerializeSchema;
	class SerializeScalarType;
	class SerializeCompoundType;
	class ByteReader;
	class ByteWriter;
	
	class SerializeCompoundType : public SerializeType
	{
	private:
		enum State
		{
			kState_Defined,
			kState_Fixing,
			kState_Ready,
		};
		
		SerializeDictionary<SerializeMember*>	m_dictionary;
		
		State			m_state;
		size_t			m_size;
		size_t			m_alignment;
		
	public:
		SerializeCompoundType()
		: m_dictionary(16, nullptr)
		, m_state(kState_Defined)
		{
		}
		
		virtual ~SerializeCompoundType();
		
		virtual SerializeStatus		ConvertOne(char*						dstData,
											   const char*					srcData,
											   const SerializeType*			srcType,
											   class SerializeAllocator&	alloc,
											   int							arrayCount=1) const;
		virtual size_t				GetSize() const
		{
			return m_size;
		}
		
		virtual size_t				GetAlignment() const
		{
			return m_alignment;
		}
		
		virtual bool				IsTerminal(const char*					data,
											   const SerializeScalarValue&	terminatorValue,
											   Hash							terminatorName) const;
		
		virtual SerializeStatus		FixUp(SerializeSchema& schema);
		
		virtual const SerializeCompoundType* AsCompoundType() const
		{
			return this;
		}
		
		const SerializeMember*		FindMember(Hash memberName) const;
		
		void						AddInstance			(Hash memberName, int count, Hash typeName);
		void						AddPointer			(Hash memberName, int count, Hash typeName);
		void						AddCountedPointer	(Hash memberName, int count, Hash typeName, Hash countName);
		void						AddStringPointer	(Hash memberName,
														 int  count,
														 Hash typeName,
														 Hash terminatorName,
														 const SerializeScalarValue& terminatorValue );

		virtual bool				IsBuiltIn() const
		{
			return false;
		}
		
		virtual void				Write(ByteWriter& writer) const;
		static SerializeCompoundType* ReadNew(ByteReader& reader);
		virtual uint64_t			GetChecksum(uint64_t basis) const;
		
	private:
		void			AddMember(Hash memberName, SerializeMember* member);
		
	};
	
} // namespace fw
